
package com.dyzx.hbb.security.filter;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dyzx.hbb.common.annotation.OperationLog;
import com.dyzx.hbb.common.constant.InitConfig;
import com.dyzx.hbb.common.utils.BufferedRequestWrapper;
import com.dyzx.hbb.common.utils.JwtUtils;
import com.dyzx.hbb.common.utils.SecurityUtils;
import com.dyzx.hbb.modules.sys.entity.SysLogOperation;
import com.dyzx.hbb.modules.sys.service.SysLogOperationService;
import com.dyzx.hbb.security.model.LoginUser;
import com.dyzx.hbb.security.service.AuthService;
import com.dyzx.hbb.security.service.UserDetailsServiceImpl;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * JWT认证过滤器
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    @Autowired
    private AuthService authService;


    @Override
    protected void initFilterBean() throws ServletException {
        super.initFilterBean();
        System.out.println("JwtAuthenticationFilter initialized");

         //   ResourceUtil.readUtf8Str("public-paths.json");
        String config = ResourceUtil.readUtf8Str("config.json");
        System.out.println(config);
        JSONObject json = JSON.parseObject(config);
        System.out.println(json.toJSONString());
        JSONObject error = json.getJSONObject("error");
        InitConfig.setErrors(error);

        JSONObject sort = json.getJSONObject("sort");
        InitConfig.setSort(sort);
        System.out.println(InitConfig.getSort());


    }

    @OperationLog
    @Override
    protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain chain)
            throws ServletException, IOException {
        
        String requestURI = request.getRequestURI();
        System.out.println("\n=== Processing request for URI: " + requestURI + " ===");
        String method = request.getMethod().toUpperCase();

    //    if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
            // CORS "pre-flight" request
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type,Authorization,language");
            response.addHeader("Access-Control-Max-Age", "1800");//30 min
     //   }




        // 检查是否是不需要验证的路径
        boolean publicPath = isPublicPath(requestURI);
        System.out.println("Is public path: " + publicPath);
        if (publicPath) {
            System.out.println("Public path detected, skipping authentication");
            chain.doFilter(request, response);
            return;
        }

        // 获取token
        String authHeader = request.getHeader("Authorization");
        System.out.println("Authorization header: " + authHeader);
        InitConfig.setRequest(request);
        String token = JwtUtils.getToken(request);
        
        if (token == null) {
            System.out.println("No token provided");
            handleAuthenticationFailure(response,401, "未提供认证令牌");
            return;
        }

        System.out.println("Extracted token: " + token.substring(0, Math.min(token.length(), 20)) + "...");
        
        try {
            if (!jwtUtils.validateToken(token)) {
                System.out.println("Token validation failed");
                handleAuthenticationFailure(response, 401,"无效的认证令牌");
                return;
            }
            if(!authService.validateToken(token)){
                System.out.println("Token validation failed");
                handleAuthenticationFailure(response, 401,"无效的认证令牌");
                return;
            }

            // 获取用户ID
            Long userId = jwtUtils.getUserId(token);
            System.out.println("Extracted userId from token: " + userId);
            
            // 获取用户信息
            UserDetails userDetails = userDetailsService.loadUserById(userId);
            System.out.println("Loaded user details: " + userDetails);
            System.out.println("User authorities: " + userDetails.getAuthorities());
            
            // 构建认证信息
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            
            // 设置认证信息
            SecurityContextHolder.getContext().setAuthentication(authentication);

            System.out.println("Authentication set in SecurityContext: " + authentication);

            // 继续处理请求
            chain.doFilter(request, response);
            
        } catch (Exception e) {
            System.out.println("=== Authentication failed ===");
            System.out.println("Error message: " + e.getMessage());
            e.printStackTrace();
            SecurityContextHolder.clearContext();
            if (e instanceof ExpiredJwtException) {
                handleAuthenticationFailure(response, 401,"认证令牌已过期");
            }else {
                handleAuthenticationFailure(response, 402, "认证处理失败");
                //  handleAuthenticationFailure(response, "认证处理失败");
            }
        }
    }


    private void handleAuthenticationFailure(HttpServletResponse response,int code, String message) throws IOException {
        SecurityContextHolder.clearContext();
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{\"code\":"+code+",\"message\":\"" + message + "\",\"data\":null}");
    }
    
    private boolean isPublicPath(String uri) {
        // 基本的公共路径
        if (uri.contains("/auth/login") || uri.contains("/sms/vcode") ||
            uri.contains("/auth/register") ||
            uri.contains("/sys/app/check") ||
            uri.contains("/auth/forgot_pass") ||
            uri.contains("/fcxs/interface") ||
            uri.contains("/v3/api-docs") ||
            uri.contains("/swagger-ui") ||
            uri.contains("/doc.html") ||
            uri.contains("/webjars/") ||
            uri.equals("/error") ||
            uri.endsWith(".js") ||
            uri.endsWith(".css") ||
            uri.endsWith(".png") ||
            uri.endsWith(".html") ||
            uri.endsWith("favicon.ico")) {
            return true;
        }

        // Swagger相关路径
        if (uri.startsWith("/swagger-resources") ||
            uri.startsWith("/v3/api-docs") ||
            uri.startsWith("/doc.html") ||
            uri.startsWith("/webjars/")) {
            return true;
        }

        // 静态资源
        if (uri.startsWith("/static/") ||
            uri.startsWith("/public/") ||
            uri.startsWith("/resources/")) {
            return true;
        }

        System.out.println("URI " + uri + " is " + (false ? "public" : "protected") + " path");
        return false;
    }

    /**
     * 检查是否是API文档相关的请求
     */
    private boolean isApiDocRequest(HttpServletRequest request) {
        String uri = request.getRequestURI();
        return uri.contains("/v3/api-docs") ||
               uri.contains("/swagger-ui") ||
               uri.contains("/doc.html") ||
               uri.contains("/webjars/");
    }

}